package com.anntly.config;

import com.anntly.aspect.DbRouteAspect;
import com.anntly.interceptor.DynamicDatasource;
import com.anntly.interceptor.TbRouteInterceptor;
import com.anntly.strategy.IDbRoute;
import com.anntly.strategy.impl.DbRouteHashPolicy;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author：Anntly
 * @Package：com.anntly.config
 * @Project：dbRouter
 * @name：DataRouteAutoConfig
 * @Date：2024/7/7 17:13
 * @Filename：DataRouteAutoConfig
 */
@Configuration
@EnableConfigurationProperties(DBRouterConfigProperties.class)
@ConditionalOnProperty(name = "db-router.enable",havingValue = "true")
public class DataRouteAutoConfig {

    @Resource
    private DBRouterConfigProperties dbRouterConfigProperties;

    @Bean
    public DbRouteAspect dbRouteAspect(){
        return new DbRouteAspect();
    }


    @Bean
    public TbRouteInterceptor tbRouteInterceptor(){
        return new TbRouteInterceptor();
    }

    @Bean
    public IDbRoute iDbRoute(){
        return new DbRouteHashPolicy();
    }

    @Bean
    public TransactionTemplate transactionTemplate(DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);

        TransactionTemplate transactionTemplate = new TransactionTemplate();
        transactionTemplate.setTransactionManager(dataSourceTransactionManager);
        transactionTemplate.setPropagationBehaviorName("PROPAGATION_REQUIRED");
        return transactionTemplate;
    }

    private DataSource createDataSource(DatasourceProperties datasourceProperties) {
        try {
            DataSourceProperties dataSourceProperties = new DataSourceProperties();
            dataSourceProperties.setUrl(datasourceProperties.getUrl());
            dataSourceProperties.setUsername(datasourceProperties.getUsername());
            dataSourceProperties.setPassword(datasourceProperties.getPassword());
            DataSource ds = dataSourceProperties.initializeDataSourceBuilder().type((Class<DataSource>) Class.forName(dataSourceProperties.getDriverClassName())).build();
            return ds;
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("can not find datasource type class by class name", e);
        }
    }

    @Bean
    public DataSource createDataSource() {
        // 创建数据源
        Map<Object, Object> targetDataSources = new HashMap<>();
        Map<String, DatasourceProperties> dbs = dbRouterConfigProperties.getDbs();
        for (String dbInfo : dbs.keySet()) {
            DatasourceProperties datasourceProperties = dbs.get(dbInfo);
            // 根据objMap创建DataSourceProperties,遍历objMap根据属性反射创建DataSourceProperties
            DataSource ds = createDataSource(datasourceProperties);
            targetDataSources.put(dbInfo, ds);

        }
        DatasourceProperties defaultDatasourceProperties = dbs.get(dbRouterConfigProperties.getDefaultDb());
        // 设置数据源
        DynamicDatasource dynamicDataSource = new DynamicDatasource();
        dynamicDataSource.setTargetDataSources(targetDataSources);
        // db0为默认数据源
        dynamicDataSource.setDefaultTargetDataSource(createDataSource(defaultDatasourceProperties));
        return dynamicDataSource;
    }
}
